Swing একটি GUI (Graphical User Interface) টুলকিট যা ইউজারের ইন্টারঅ্যাকশনের জন্য সরাসরি থ্রেড ব্যবহৃত করে। যেহেতু Swing অ্যাপ্লিকেশনগুলো সাধারণত ইভেন্ট-ড্রিভেন (Event-driven) হয়, তাই ইউজারের ইন্টারফেসের জন্য একটি মূল (UI) থ্রেড থাকে, যা মূলত সমস্ত GUI কম্পোনেন্ট যেমন বাটন, টেক্সট ফিল্ড, টেবিল ইত্যাদি পরিচালনা করে। কিন্তু, যদি আপনি দীর্ঘ সময় ধরে চলা কাজ, যেমন নেটওয়ার্ক কল, ফাইল অপারেশন, বা বড় ডেটা প্রসেসিং করতে চান, তবে তা UI থ্রেডে করার ফলে অ্যাপ্লিকেশন স্লো বা ফ্রিজ হতে পারে।
এই সমস্যা সমাধানের জন্য SwingWorker ব্যবহার করা হয়। SwingWorker একটি বিশেষ ক্লাস যা Swing এ মাল্টিথ্রেডিং কার্যক্রম পরিচালনা করতে সহায়ক। এটি UI থ্রেডকে অবরুদ্ধ (blocked) না করে ব্যাকগ্রাউন্ডে দীর্ঘস্থায়ী কাজ চালাতে পারে।
SwingWorker-এ তিনটি মূল মেথড থাকে, যেগুলোর মাধ্যমে আমরা ব্যাকগ্রাউন্ড টাস্ক পরিচালনা করতে পারি:
doInBackground()
কাজ সম্পন্ন হয়ে যায়।ধরা যাক, আমরা একটি ব্যাকগ্রাউন্ড টাস্ক (যেমন একটি ফাইল ডাউনলোড করা) চালাতে চাই এবং তার অগ্রগতি UI তে দেখাতে চাই।
import javax.swing.*;
import java.awt.*;
import java.util.List;
public class SwingWorkerExample {
public static void main(String[] args) {
JFrame frame = new JFrame("SwingWorker Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// প্রোগ্রেস বারের জন্য একটি JPanel তৈরি
JPanel panel = new JPanel();
JProgressBar progressBar = new JProgressBar(0, 100);
panel.add(progressBar);
// JButton তৈরি করা
JButton startButton = new JButton("কাজ শুরু করুন");
// JButton ক্লিক করলে SwingWorker চালানো হবে
startButton.addActionListener(e -> {
// SwingWorker ব্যবহার করে ব্যাকগ্রাউন্ড কাজ
Task task = new Task(progressBar);
task.execute();
});
// JFrame এ UI উপাদান যোগ করা
panel.add(startButton);
frame.add(panel);
// JFrame আকার এবং দৃশ্যমান করা
frame.setSize(300, 150);
frame.setVisible(true);
}
}
class Task extends SwingWorker<Void, Integer> {
private JProgressBar progressBar;
// কনস্ট্রাক্টর
public Task(JProgressBar progressBar) {
this.progressBar = progressBar;
}
@Override
protected Void doInBackground() throws Exception {
// ব্যাকগ্রাউন্ড কাজ (যেমন ডাউনলোড বা বড় প্রসেস)
for (int i = 0; i <= 100; i++) {
Thread.sleep(50); // ডিলে যোগ করা
publish(i); // progress বার আপডেট করা
}
return null;
}
@Override
protected void process(List<Integer> chunks) {
// UI আপডেট করার জন্য progress বারকে আপডেট করা
int progress = chunks.get(chunks.size() - 1);
progressBar.setValue(progress);
}
@Override
protected void done() {
// কাজ শেষ হলে একটি মেসেজ দেখানো
try {
get(); // ব্যাকগ্রাউন্ড থ্রেডের ফলাফল নিয়ে আসে
JOptionPane.showMessageDialog(null, "কাজ সম্পন্ন হয়েছে!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
Task
ক্লাসটি SwingWorker
ইমপ্লিমেন্ট করেছে। এটি একটি দীর্ঘস্থায়ী কাজ (যেমন লুপ) সম্পাদন করে এবং তার অগ্রগতি UI তে প্রকাশ করে।publish(i)
কল করা হচ্ছে।publish()
ব্যাকগ্রাউন্ড থ্রেডে থেকে ডেটা প্রকাশ করতে সাহায্য করে, এবং process()
মেথডটি UI থ্রেডে ডেটা আপডেট করে।done()
মেথডটি কল হয় এবং এখানে আমরা কাজের সম্পন্ন হওয়া সম্পর্কে ব্যবহারকারীকে একটি মেসেজ প্রদর্শন করি।cancel(true)
মেথড ব্যবহার করে ব্যাকগ্রাউন্ড টাস্কটি ক্যানসেল করতে পারেন। এটি একটি শর্তযুক্ত কাজ হিসাবে প্রযোজ্য।SwingWorker হল Swing অ্যাপ্লিকেশনে মাল্টিথ্রেডিং পরিচালনার একটি অত্যন্ত গুরুত্বপূর্ণ ক্লাস। এটি UI থ্রেডকে অবরুদ্ধ না করে ব্যাকগ্রাউন্ড থ্রেডে দীর্ঘস্থায়ী কাজ করার সুবিধা দেয়। doInBackground()
, process()
, এবং done()
মেথডের মাধ্যমে আপনি ব্যাকগ্রাউন্ড কাজ সম্পন্ন করার সময় UI আপডেট করতে পারেন। এটি ব্যবহার করে আপনি একটি নিরবচ্ছিন্ন এবং দ্রুত ইউজার ইন্টারফেস তৈরি করতে সক্ষম হন।
Swing একটি গ্রাফিক্যাল ইউজার ইন্টারফেস (GUI) টুলকিট যা Java প্রোগ্রামিং ভাষায় ডেক্সটপ অ্যাপ্লিকেশন তৈরি করার জন্য ব্যবহৃত হয়। Swing-এ multithreading ব্যবহারের প্রয়োজনীয়তা খুবই গুরুত্বপূর্ণ, কারণ এটি GUI অ্যাপ্লিকেশনগুলোর পারফরম্যান্স এবং ইউজার ইন্টারঅ্যাকশনকে উন্নত করতে সহায়তা করে।
এখানে, Swing-এ multithreading ব্যবহারের গুরুত্ব এবং প্রয়োজনীয়তা তুলে ধরা হয়েছে।
Swing UI কম্পোনেন্টগুলির বেশিরভাগই single-threadedভাবে কাজ করে এবং তাদের Event Dispatch Thread (EDT) এর মাধ্যমে পরিচালনা করা হয়। কিন্তু যদি আপনি long-running tasks (যেমন, ডেটাবেস থেকে ডাটা লোড করা বা ফাইল প্রসেসিং) GUI থ্রেডে রান করতে চান, তাহলে এটি GUI সিস্টেমের responsiveness কমিয়ে দিতে পারে। এর ফলে অ্যাপ্লিকেশন হ্যাং বা ফ্রিজ হতে পারে।
Multithreading এর মাধ্যমে আপনি দীর্ঘস্থায়ী কাজগুলো GUI থ্রেড থেকে আলাদা থ্রেডে চালাতে পারবেন, যাতে ইউজার ইন্টারফেস ব্লক না হয় এবং অ্যাপ্লিকেশনটি আরো দ্রুত এবং প্রতিক্রিয়াশীল থাকে।
যদি আপনি একটি লম্বা প্রসেসিং ফাইল প্রক্রিয়াকরণ এক্সিকিউট করেন GUI থ্রেডে, তাহলে পুরো অ্যাপ্লিকেশনটি অপ্রতিক্রিয়াশীল হয়ে যাবে যতক্ষণ না প্রসেসটি শেষ হয়। তবে, যদি আপনি separate worker thread ব্যবহার করেন, তাহলে ইউজার ইন্টারফেস চলমান থাকবে এবং ব্যবহারকারী অন্যান্য কাজ করতে পারবে।
Swing অ্যাপ্লিকেশনে Event Dispatch Thread (EDT) হলো একমাত্র থ্রেড যা GUI কম্পোনেন্টের সাথে ইন্টারঅ্যাকশন করে (যেমন, বাটন ক্লিক, মেনু সিলেকশন, বা উইন্ডো রেন্ডারিং)। এর মানে, সমস্ত UI আপডেট এবং ইভেন্ট হ্যান্ডলিং শুধু EDT-এ ঘটবে।
Multithreading এর সাহায্যে আপনি যখন দীর্ঘ-running কাজ পরিচালনা করেন, তখন সেগুলি EDT-কে অবরুদ্ধ না করে একটি পৃথক থ্রেডে রান করা উচিত। যদি আপনি দীর্ঘ-running কাজ সরাসরি EDT-এ চালান, তবে এটি UI freeze করতে পারে এবং lag সৃষ্টি করতে পারে।
SwingWorker ক্লাস ব্যবহার করে একটি ব্যাকগ্রাউন্ড থ্রেড তৈরি করা যায়, যা দীর্ঘ-running কাজ EDT থেকে আলাদা রাখে এবং UI thread-এর responsiveness বজায় রাখে।
import javax.swing.*;
import java.awt.event.*;
public class MultithreadingExample {
public static void main(String[] args) {
JFrame frame = new JFrame("Swing Multithreading Example");
JButton button = new JButton("Start Task");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Long-running task in background thread
SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
// Simulating long-running task
Thread.sleep(5000);
return null;
}
@Override
protected void done() {
// Update UI after task completion
JOptionPane.showMessageDialog(frame, "Task Completed!");
}
};
worker.execute();
}
});
frame.add(button);
frame.setSize(300, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
Multithreading ব্যবহার করার অন্যতম প্রধান কারণ হল UI responsiveness বজায় রাখা। যখন একটি ইউজার অ্যাপ্লিকেশন ব্যবহার করছে, তারা অপেক্ষা করতে চাইবে না যদি কোনো দীর্ঘ-running কাজ চলছে। SwingWorker বা Thread ব্যবহার করে আপনি একটি আলাদা থ্রেডে সেই কাজটি করতে পারেন এবং ব্যবহারকারীকে একটি লোডিং বা প্রগ্রেস বারও দেখাতে পারেন। এর মাধ্যমে অ্যাপ্লিকেশনটি সেমি-ইন্টারঅ্যাকটিভ থাকবে এবং ব্যবহারকারী একটি পরিষ্কার অনুভূতি পাবে যে অ্যাপ্লিকেশনটি কাজ করছে।
Multithreading এর মাধ্যমে আপনি সহজেই UI thread-এ কাজ না করে অন্য থ্রেডে কাজ সম্পন্ন করতে পারেন, এবং কাজ শেষ হওয়ার পরে UI তে ফলাফল আপডেট করতে পারেন। এটি মূলত দীর্ঘ-running কাজের শেষে ফলাফল প্রসেসিং বা UI আপডেট করার ক্ষেত্রে কাজে আসে।
ব্যাকগ্রাউন্ড থ্রেডে ডেটা লোড করা এবং এর পরে UI তে প্রিন্ট করা:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.List;
public class BackgroundTaskExample {
public static void main(String[] args) {
JFrame frame = new JFrame("Background Task Example");
JTextArea textArea = new JTextArea(10, 30);
JButton button = new JButton("Start Task");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Background task using SwingWorker
SwingWorker<List<String>, Void> worker = new SwingWorker<List<String>, Void>() {
@Override
protected List<String> doInBackground() throws Exception {
// Simulating long-running task (data loading)
Thread.sleep(3000);
return List.of("Data 1", "Data 2", "Data 3");
}
@Override
protected void done() {
try {
// Update UI with the result
List<String> data = get();
for (String line : data) {
textArea.append(line + "\n");
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
worker.execute();
}
});
frame.setLayout(new FlowLayout());
frame.add(button);
frame.add(new JScrollPane(textArea));
frame.setSize(400, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
Swing অ্যাপ্লিকেশনের জন্য Thread Safety গুরুত্বপূর্ণ বিষয়। Swing-এর সমস্ত UI আপডেট Event Dispatch Thread (EDT) এর মাধ্যমে হওয়া উচিত। Multithreading ব্যবহারের মাধ্যমে UI থ্রেডকে অবরুদ্ধ না করে অন্য থ্রেডে কাজ সম্পন্ন করা যেতে পারে। SwingWorker এবং invokeLater() মেথড ব্যবহার করে এটি নিশ্চিত করা সম্ভব যে UI আপডেট সঠিকভাবে EDT-এ হবে।
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// Code to update the UI
}
});
এটি UI তে কাজ আপডেট করার জন্য EDT ব্যবহার নিশ্চিত করে, এবং এটি thread-safe।
Swing অ্যাপ্লিকেশনগুলিতে Multithreading এর ব্যবহার UI responsiveness এবং performance বৃদ্ধি করতে সাহায্য করে, বিশেষ করে যখন অ্যাপ্লিকেশনটি বৃহত্তর এবং ডেটা-ইনটেনসিভ হয়।
Swing-এ SwingWorker একটি শক্তিশালী ক্লাস যা UI থ্রেড থেকে দীর্ঘ-running (background) কাজগুলো পরিচালনা করতে ব্যবহৃত হয়, যাতে UI responsive (প্রতিক্রিয়াশীল) থাকে। সাধারণত, Swing অ্যাপ্লিকেশনগুলোতে UI থ্রেড (Event Dispatch Thread বা EDT) ব্যবহারকারীর ইন্টারঅ্যাকশনের জন্য দায়ী থাকে, যেমন বাটনে ক্লিক করা, মাউস মুভমেন্ট ইত্যাদি। কিন্তু, যদি কোনো দীর্ঘ-running কাজ (যেমন ফাইল ডাউনলোড, ডেটাবেস থেকে তথ্য নিয়ে আসা ইত্যাদি) UI থ্রেডে করা হয়, তবে UI "hang" বা স্লো হয়ে যেতে পারে। এই সমস্যা থেকে রক্ষা পেতে SwingWorker ব্যবহার করা হয়।
SwingWorker এর মাধ্যমে আমরা দীর্ঘ-running কাজগুলো background থ্রেডে চালাতে পারি এবং UI থ্রেডে ফলাফল বা অবস্থা জানাতে পারি।
SwingWorker মূলত দুটি জেনেরিক প্যারামিটার নেয়:
SwingWorker-এ সাধারণত তিনটি মূল মেথড থাকে:
এখানে একটি উদাহরণ দেওয়া হলো যেখানে SwingWorker ব্যবহার করে একটি দীর্ঘ-running কাজ (যেমন ডেটা লোড করা) background থ্রেডে সম্পন্ন করা হচ্ছে, এবং UI থ্রেডে প্রগ্রেস বার দেখানো হচ্ছে।
import javax.swing.*;
import java.awt.*;
import java.util.List;
import java.util.ArrayList;
public class SwingWorkerExample {
public static void main(String[] args) {
// JFrame তৈরি করা
JFrame frame = new JFrame("SwingWorker Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 200);
// JPanel তৈরি করা
JPanel panel = new JPanel();
frame.add(panel);
// JLabel এবং JProgressBar তৈরি করা
JLabel label = new JLabel("Loading...");
JProgressBar progressBar = new JProgressBar(0, 100);
progressBar.setStringPainted(true);
panel.add(label);
panel.add(progressBar);
// JFrame দেখানো
frame.setVisible(true);
// SwingWorker ব্যবহার করে background task চালানো
SwingWorker<Void, Integer> worker = new SwingWorker<Void, Integer>() {
@Override
protected Void doInBackground() throws Exception {
// দীর্ঘ-running কাজ, যেমন ডেটা লোড বা প্রসেসিং
for (int i = 0; i <= 100; i++) {
// কাজের প্রগতি আপডেট করা
publish(i);
Thread.sleep(50); // ৫০ মিলিসেকেন্ড বিরতি
}
return null;
}
@Override
protected void process(List<Integer> chunks) {
// প্রগতি আপডেট করা UI থ্রেডে
int progress = chunks.get(chunks.size() - 1);
progressBar.setValue(progress);
label.setText("Progress: " + progress + "%");
}
@Override
protected void done() {
// কাজ শেষ হলে UI আপডেট
label.setText("Task Completed!");
}
};
// SwingWorker শুরু করা
worker.execute();
}
}
SwingWorker<Void, Integer>
- এখানে Void
মানে যে কাজের কোনও রিটার্ন ভ্যালু নেই, এবং Integer
হল প্রগ্রেস আপডেটের জন্য ব্যবহৃত ভ্যালু (যেমন ১ থেকে ১০০ পর্যন্ত প্রগ্রেস প্যারামিটার)।Thread.sleep(50)
ব্যবহার করে প্রতিটি চক্রে ৫০ মিলিসেকেন্ড বিরতি দেওয়া হচ্ছে, যা প্রকৃত কাজের সিমুলেশন।publish()
থেকে প্রগ্রেস আপডেট গ্রহণ করে এবং UI থ্রেডে প্রগ্রেস বার আপডেট করে।chunks
-এর মধ্যে প্রতিটি প্রগ্রেস মান আসে এবং UI থ্রেডে সেটি আপডেট করা হয়।Task Completed!
মেসেজ দেখানো হয়।SwingWorker
শুরু করার জন্য execute()
মেথডটি কল করা হয়।SwingWorker ব্যবহার করার মাধ্যমে আপনি UI থ্রেডে কোনও দীর্ঘ-running কাজ চালাতে পারবেন না, তবে আপনি সেই কাজটিকে background থ্রেডে চালিয়ে UI থ্রেডকে অপ্রতিবন্ধক রাখতে পারেন। এটি বিশেষভাবে দরকারি যখন আপনি ডেটাবেস বা নেটওয়ার্ক অপারেশন, বড় ফাইলের প্রসেসিং বা অন্যান্য সময়সাপেক্ষ কাজ পরিচালনা করেন।
SwingWorker ব্যবহার করে আপনি সহজেই:
SwingWorker-এ doInBackground() ব্যবহার করে background task চালানো হয়, এবং process() ও done() মেথড ব্যবহার করে UI থ্রেডে প্রগ্রেস এবং ফলাফল আপডেট করা হয়। এটি UI থ্রেডকে হ্যাং বা স্লো না হওয়ার জন্য সহায়তা করে এবং ব্যবহারকারীকে কাজের প্রগ্রেস সম্পর্কে জানানোর সুযোগ দেয়। SwingWorker ব্যবহারের মাধ্যমে আপনি UI responsive রাখতে পারেন এবং background task পরিচালনা করতে পারেন।
Swing-এ Multithreading এবং SwingWorker ব্যবহৃত হয় দীর্ঘ সময়ের কাজ সম্পাদন করতে, যেমন ইন্টারনেট থেকে ডেটা লোড করা বা বড় ফাইল প্রক্রিয়া করা, কিন্তু GUI থ্রেডটি (UI) বন্ধ না হওয়া নিশ্চিত করতে।
Swing এর GUI থ্রেড একে অপরের সাথে একযোগভাবে কাজ করার জন্য টাস্কগুলোকে SwingWorker বা Multithreading ব্যবহারের মাধ্যমে ব্যাকগ্রাউন্ড থ্রেডে চালানো হয়। এটি ব্যবহৃত হয় মূল GUI থ্রেডকে ব্লক না করে ব্যবহারকারীর সাথে ইন্টারঅ্যাকশন বজায় রাখতে।
Multithreading-এর মাধ্যমে আমরা GUI থ্রেডের সাথে ব্যাকগ্রাউন্ড থ্রেডগুলিকে কার্যকরভাবে পরিচালনা করতে পারি। তবে, Swing GUI কম্পোনেন্টগুলির মধ্যে সরাসরি থ্রেড ব্যবহারের ফলে সমস্যা হতে পারে, যেমন UI থ্রেডের সাথে একযোগভাবে কাজ করতে না পারা বা GUI থ্রেডকে ব্লক করা।
তবে SwingWorker একটি বিশেষ ক্লাস, যা ব্যাকগ্রাউন্ড থ্রেডে কাজ সম্পাদন করতে সহায়ক এবং GUI থ্রেডের সাথে সঠিকভাবে কাজ করতে পারে।
এই উদাহরণে, একটি SwingWorker ক্লাস ব্যবহার করা হয়েছে যা ব্যাকগ্রাউন্ড থ্রেডে কিছু দীর্ঘ সময়ের কাজ সম্পাদন করবে (যেমন একটি বড় সংখ্যা গণনা করা), এবং UI থ্রেডে অগ্রগতি আপডেট করবে।
import javax.swing.*;
import java.util.concurrent.ExecutionException;
public class SwingWorkerExample {
public static void main(String[] args) {
// JFrame তৈরি
JFrame frame = new JFrame("SwingWorker Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 200);
// JLabel এবং JProgressBar তৈরি
JLabel label = new JLabel("Processing...");
JProgressBar progressBar = new JProgressBar(0, 100);
progressBar.setStringPainted(true); // প্রোগ্রেস বারটি দেখা যাবে
frame.setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS));
frame.add(label);
frame.add(progressBar);
// SwingWorker ব্যবহার করে দীর্ঘ কাজ
SwingWorker<Void, Integer> worker = new SwingWorker<Void, Integer>() {
@Override
protected Void doInBackground() throws Exception {
for (int i = 0; i <= 100; i++) {
Thread.sleep(50); // প্রতিটি ধাপে 50 মিলিসেকেন্ড দেরি
publish(i); // অগ্রগতি আপডেট
}
return null;
}
@Override
protected void process(java.util.List<Integer> chunks) {
// UI থ্রেডে অগ্রগতি আপডেট করা
int progress = chunks.get(chunks.size() - 1);
progressBar.setValue(progress);
}
@Override
protected void done() {
// কাজ শেষ হলে UI আপডেট
label.setText("Task Completed!");
}
};
// কাজ শুরু করা
worker.execute();
// JFrame প্রদর্শন করা
frame.setVisible(true);
}
}
Void
(কোন রিটার্ন টাইপ নেই) এবং Integer
(অগ্রগতির মান পাঠানোর জন্য)।doInBackground()
মেথডে আমরা ব্যাকগ্রাউন্ড কাজটি সম্পাদন করি (যেমন গণনা, ফাইল লোড করা ইত্যাদি)।process()
মেথডে আমরা UI-তে অগ্রগতির মান আপডেট করি (এখানে JProgressBar ব্যবহার করা হয়েছে)।done()
মেথডটি তখন কল করা হয় যখন কাজ সম্পন্ন হয়, এবং UI-তে ফলাফল দেখানো হয়।এই উদাহরণে আমরা একটি সাধারণ Thread
ব্যবহার করে একটি দীর্ঘ সময়ের কাজ চালাবো।
import javax.swing.*;
public class MultithreadingExample {
public static void main(String[] args) {
// JFrame তৈরি
JFrame frame = new JFrame("Multithreading Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 200);
// JLabel তৈরি
JLabel label = new JLabel("Processing...");
frame.add(label);
// Thread ব্যবহার করে দীর্ঘ কাজ
Thread worker = new Thread(new Runnable() {
@Override
public void run() {
try {
for (int i = 0; i <= 100; i++) {
Thread.sleep(50); // প্রতিটি ধাপে 50 মিলিসেকেন্ড দেরি
// UI থ্রেডে কাজ করা
final int progress = i;
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
label.setText("Progress: " + progress + "%");
}
});
}
label.setText("Task Completed!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
// কাজ শুরু করা
worker.start();
// JFrame প্রদর্শন করা
frame.setVisible(true);
}
}
Thread
তৈরি করেছি যা একটি দীর্ঘ সময়ের কাজ সম্পাদন করবে (যেমন স্লিপ করা, গণনা করা ইত্যাদি)।SwingUtilities.invokeLater()
ব্যবহার করা হয়েছে যাতে UI থ্রেডে কাজ করা যায়। এটি নিশ্চিত করে যে UI আপডেট শুধুমাত্র UI থ্রেডেই করা হবে।SwingWorker
বা SwingUtilities.invokeLater()
ব্যবহার করা উচিত।Read more